<?php
/* Sort by extension, case-insensitive. */
function file_cmp($a, $b) {
	global $file_path;

	if ($a == $b) return 0;

	return strcmp(strtolower($a), strtolower($b));
/*
	$ai = pathinfo($file_path . '/' . $a, PATHINFO_EXTENSION | PATHINFO_FILENAME);
	$bi = pathinfo($file_path . '/' . $b, PATHINFO_EXTENSION | PATHINFO_FILENAME);

	$ext = strcmp(strtolower($ai['extension']), strtolower($bi['extension']));
	if ($ext) return $ext;
	else      return strcmp(strtolower($a), strtolower($b));
*/
}

/* Sort case-insensitive. */
function dir_cmp($a, $b) {
	return strcmp(strtolower($a), strtolower($b));
}

/* Convert bytes to human-readable using binary. */
function human_size($bytes, $precision = 2) {
	$units = array('B', 'kB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB'/*, 'YB'*/);
	foreach ($units as $u) {
		if ($bytes < 1024) return sprintf("%" . ($precision + 8) . "s", sprintf("%.${precision}f %2s", $bytes, $u));
		else $bytes = $bytes / 1024;
	}
	return sprintf("%.${precision}f YB", $bytes);
}

function web_friendly($text, $do_links = false) {
	$bad  = array("&",     "<",    ">",    '"');
	$good = array("&amp;", "&lt;", "&gt;", "&quot;");
	$text = str_replace($bad, $good, $text);
	if ($do_links) {
		// don't need to go OTT here...
		$proto  = '(?:https?|s?ftp)://';
		$proper = "(?:${proto})?"						// protocol
				. '[A-Z0-9][A-Z0-9-]*(?:\.[^/\s.]+)+'	// server
				. '(?:/[^/\s\?]+)*'						// path
				. '(?:\?[^\s]+)?'						// query
				;
		$wwwdot = 'www(?:\.[A-Z0-9-]+)+';
		$dotcom = '(?:[A-Z0-9][A-Z0-9-]*\.)+(?:(?:com|net|org)(?:\.au|\.ca)?|co\.(?:uk|nz))';

		$regexp = "!(${proper}|${wwwdot}|${dotcom})(.*)!i";
		//$regexp = "!(${proper})(.*)!i";

		$oldtext = $text;
		$newtext = '';
		while (preg_match($regexp, $oldtext, $matches, PREG_OFFSET_CAPTURE)) {
			$prefix = substr($oldtext, 0, $matches[1][1]);
			$url = $matches[1][0];
			if (!preg_match("!${proto}!i", $url)) {
				$url = 'http://' . $url;
			}
			$newtext .= $prefix . '<a href="' . $url . '">' . $matches[1][0] . '</a>';
			$oldtext = $matches[2][0];
		}
		$text = $newtext . $oldtext;
	}
	return $text;
}

function link_friendly($text) {
	if (preg_match_all('/([A-Z0-9\._-]+)|([^A-Z0-9\._-])/i', $text, $matches, PREG_SET_ORDER)) {
		$result = '';
		foreach ($matches as $match) {
			if ($match[1]) {
				$result .= $match[1];
			} else {
				$result .= sprintf('%%%02X', ord($match[2]));
			}
		}
		return $result;
	} else {
		return $text;
	}
}
?>
<html>
<head>
<title><?php echo $SETTINGS['TITLE']; ?></title>
<style type="text/css">
* { font-family: "Times New Roman", Times, serif; }
pre, pre *, code { font-family: "Lucida Console", monospace; }
a:link { color: #00f; }
a:visited { color: #03f; }
a:hover, a:active { color: #09f; }
</style>
<?php echo $SETTINGS['FAVICON']; ?>
</head>
<body>
<?php
$file_path = dirname($_SERVER['SCRIPT_FILENAME']);
$http_path = dirname($_SERVER['PHP_SELF']);
$index = basename($_SERVER['SCRIPT_FILENAME']);

$show_hidden = false;

if (isset($_GET['showhidden']) && $_GET['showhidden']) {
	$show_hidden = true;
}

$tmp = file_get_contents('.descriptions');
$descr = array();
$hide = array();
$tmp = preg_replace('/\s*#.*$/m', '', $tmp);
if (preg_match_all('/^\s*([^#][^\t]*)\t+(.+)$/m', $tmp, $matches, PREG_SET_ORDER)) {
	foreach ($matches as $match) {
		if (preg_match('/^\s*\*HIDE\*\s*(.*)$/', $match[2], $hidden)) {
			$hide[$match[1]] = $match[1];
			$descr[$match[1]] = $hidden[1];
		} else {
			$descr[$match[1]] = $match[2];
		}
	}
}

$d = dir($file_path);
if ($d) {
	$maxlen = 0;

	$files = array();
	$dirs  = array();
	while (false !== ($entry = $d->read())) {
		if ($show_hidden) {
			$okay = ($entry && $entry != '.' && $entry != '..');
		} else {
			$okay = ($entry && $entry{0} != '.' && $entry != $index /*&& $entry != 'index.php'*/ && !preg_match('/\.inc\.php$/i', $entry) && !isset($hide[$entry]));
		}
		if ($okay) {
			$maxlen = max($maxlen, strlen($entry));
			if (is_dir($file_path . '/' . $entry)) {
				$dirs[] = $entry;
			} else {
				$files[] = $entry;
			}
		}
	}

	usort($files, 'file_cmp');
	usort($dirs, 'dir_cmp');

	echo "<pre>\n";
	echo "<h1>$http_path</h1>\n";
	foreach ($dirs as $entry) {
		echo "<a href=\"" . link_friendly($entry) . "\">" . web_friendly($entry) . "/</a>";
		for ($i = strlen($entry) + 1; $i < $maxlen; $i++) {
			echo " ";
		}
		echo "   ";
		echo date('Y-m-d H:i:s', filemtime($file_path . '/' . $entry));
		echo "   ";
		echo human_size(filesize($file_path . '/' . $entry));
		if (isset($descr[$entry])) {
			echo "   ";
			$hidden = isset($hide[$entry]);
			if ($hidden) echo "<i>";
			echo web_friendly($descr[$entry], true);
			if ($hidden) echo "</i>";
		}
		echo "\n";
	}
	if ($dirs && $files) {
		echo "<hr size=\"1\">";
	}
	foreach ($files as $entry) {
		echo "<a href=\"" . link_friendly($entry) . "\">" . web_friendly($entry) . "</a>";
		for ($i = strlen($entry); $i < $maxlen; $i++) {
			echo " ";
		}
		echo "   ";
		echo date('Y-m-d H:i:s', filemtime($file_path . '/' . $entry));
		echo "   ";
		echo human_size(filesize($file_path . '/' . $entry));
		if (isset($descr[$entry])) {
			echo "   ";
			$hidden = isset($hide[$entry]);
			if ($hidden) echo "<i>";
			echo web_friendly($descr[$entry], true);
			if ($hidden) echo "</i>";
		}
		echo "\n";
	}
	if ($hide) {
		echo "<hr size=\"1\">* ";
		if ($show_hidden) {
			echo "<a href=\"" . link_friendly($index) . "?dir\">hide</a>";
		} else {
			echo "<a href=\"" . link_friendly($index) . "?dir&showhidden=1\">show</a>";
		}
		echo " hidden entries";
	}
	echo "</pre>";
}
?>
</body>
</html>

